// MconvertDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Mconvert.h"
#include "MconvertDlg.h"
#include <atlbase.h>

#ifdef MEDIAINFO_LIBRARY
#include "MediaInfo/MediaInfo.h" //Staticly-loaded library (.lib or .a or .so)
#define MediaInfoNameSpace MediaInfoLib;
#else //MEDIAINFO_LIBRARY
#include "MediaInfoDLL/MediaInfoDLL.h" //Dynamicly-loaded library (.dll or .so)
#define MediaInfoNameSpace MediaInfoDLL;
#endif //MEDIAINFO_LIBRARY
#include <iostream> 
#include <cstdlib> 
#include <stdio.h> 
#include <string>
using namespace MediaInfoNameSpace;

#define OUTPUT_W	176
#define OUTPUT_H	128 

int ANSIToUTF8(char* pszCode, char* UTF8code);

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMconvertDlg dialog

CMconvertDlg::CMconvertDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMconvertDlg::IDD, pParent)
	,m_width(0), m_height(0), m_pfile(NULL), m_segment(0)
{
	//{{AFX_DATA_INIT(CMconvertDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMconvertDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMconvertDlg)
	DDX_Control(pDX, IDC_LIST_CVT_CLIP, m_cliplist);
	//}}AFX_DATA_MAP
	DDX_Control(pDX, IDC_CHECK_FORECE_16_9, m_cbForceWideScreen);
}

BEGIN_MESSAGE_MAP(CMconvertDlg, CDialog)
	//{{AFX_MSG_MAP(CMconvertDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_GETINFO, OnButtonGetInfo)
	ON_BN_CLICKED(IDC_BUTTON_ADD, OnButtonAddClip)
	ON_BN_CLICKED(IDC_BUTTON_SAVEREG, OnButtonSavereg)
	ON_BN_CLICKED(IDC_BUTTON_RUN, OnButtonRun)
	ON_WM_DROPFILES()
	ON_WM_CLOSE()
	ON_BN_CLICKED(IDC_BUTTON_REMOVE, OnButtonRemove)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMconvertDlg message handlers

BOOL CMconvertDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	HKEY hroot = HKEY_LOCAL_MACHINE;
	HKEY hkey;
	LONG result;
    const char *subkey	= "Software\\Meizu\\Mconvert";
	DWORD type			= REG_SZ;
	DWORD cbData;
	DWORD dwDisposition;
	const char *default_binPath = "D:\\Program Files\\FFMPEG";
	const char *default_outPath = "F:\\bt\\sa";
	CString strBinPath, strOutPath;

	result = ::RegOpenKeyEx(hroot, subkey, 0, KEY_READ, &hkey); 
	if (result == ERROR_SUCCESS) { 
		BYTE ffmpeg_bin[128] = {0};
		cbData = 128;
		result = ::RegQueryValueEx(hkey, "BinPath", NULL, &type, ffmpeg_bin, &cbData);    
		if (ERROR_SUCCESS != result) {       
			AfxMessageBox("cannot query reg", MB_OK, MB_ICONERROR);
			return FALSE;
		}
		strBinPath = ffmpeg_bin;
		
		BYTE out_path[128] = {0};
		cbData = 128;
		result = ::RegQueryValueEx(hkey, "OutPath", NULL, &type, out_path, &cbData);    
		if (ERROR_SUCCESS != result) {       
			AfxMessageBox("cannot query reg", MB_OK, MB_ICONERROR);
			return FALSE;
		}
		strOutPath = out_path;
	}
	else {
		result = RegCreateKeyEx(hroot, subkey, 0, NULL, 
			REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition);
		if (result == ERROR_SUCCESS) {
			result = RegSetValueEx(hkey, 
				"BinPath", 0, REG_SZ, 
				(CONST BYTE *)default_binPath, 
				(DWORD)(strlen(default_binPath) + 1));
			if ( result != ERROR_SUCCESS ){
				AfxMessageBox("failed to load default bin path", MB_OK, MB_ICONERROR);
				::RegCloseKey(hkey); 
				return FALSE;
			}
			
			result = RegSetValueEx(hkey, 
				"OutPath", 0, REG_SZ, 
				(CONST BYTE *)default_outPath, 
				(DWORD)(strlen(default_outPath) + 1));
			if ( result != ERROR_SUCCESS ){
				AfxMessageBox("failed to load default out path", MB_OK, MB_ICONERROR);
				::RegCloseKey(hkey); 
				return FALSE;
			}

			strBinPath = default_binPath;
			strOutPath = default_outPath;
		}
		else {
			AfxMessageBox("failed to create reg key", MB_OK, MB_ICONERROR);
			return FALSE;
		}
	} 
    
	::RegCloseKey(hkey); 

	SetDlgItemText(IDC_EDIT_FILENAME, "F:\\bt\\sa\\ep06.mp4");
	SetDlgItemText(IDC_EDIT_OUT_FILENAME, strOutPath);
	SetDlgItemText(IDC_EDIT_TIME_FROM, "00:01:00");
	SetDlgItemText(IDC_EDIT_TIME_DURATION, "00:05:00");
	SetDlgItemText(IDC_EDIT_FFMPEG_BIN, strBinPath);
	SetDlgItemText(IDC_EDIT_SEGMENT, "01");

	m_cliplist.DeleteAllItems();
	m_cliplist.InsertColumn(0,_T("file"));
	m_cliplist.InsertColumn(1,_T("start"));
	m_cliplist.InsertColumn(2,_T("duration"));
	m_cliplist.SetColumnWidth(0, 120);
	m_cliplist.SetColumnWidth(1, 80);
	m_cliplist.SetColumnWidth(2, 80);
	//m_cliplist.SetRedraw(FALSE);
	
	DragAcceptFiles(TRUE);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMconvertDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMconvertDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CMconvertDlg::OnButtonGetInfo() 
{
	// TODO: Add your control notification handler code here
	MediaInfo mi;
	CString strFilename, strDuration;
	int hour, minute, sec;
	int total_sec;
	int temp;
	GetDlgItemText(IDC_EDIT_FILENAME, strFilename);

	if (mi.Open(strFilename.GetBuffer(0))) { 
		mi.Option(__T("Complete"), __T("1")); 
		
		String info_filesize    = mi.Get(Stream_General, 0, String(__T("FileSize"))); 
		std::cout  << "file size: " <<info_filesize <<std::endl;
		
		String info_width     = mi.Get(Stream_Video, 0, String(__T("Width"))); 
		SetDlgItemText(IDC_STATIC_WIDTH, info_width.c_str());
		m_width = atoi(info_width.c_str());
		
		String info_height     = mi.Get(Stream_Video, 0, String(__T("Height"))); 
		SetDlgItemText(IDC_STATIC_HEIGHT, info_height.c_str());
		m_height= atoi(info_height.c_str());
		
		String info_duration     = mi.Get(Stream_Video, 0, String(__T("Duration"))); 
		total_sec = atoi(info_duration.c_str()) / 1000;
		// 3860
		hour	= total_sec / 3600; // 1
		temp	= total_sec % 3600; // 260
		minute	= temp / 60;		// 4
		sec		= temp % 60;		// 20

		String info_aspect_ratio = mi.Get(Stream_Video, 0, String(__T("DisplayAspectRatio")));//Display aspect ratio 
		SetDlgItemText(IDC_STATIC_ASPECT_RATIO, info_aspect_ratio.c_str());
		double aspect = atof(info_aspect_ratio.c_str());
		if(aspect >= 2.45)
			m_aspect_ratio = "5:2";
		else if(aspect >= 1.76)
			m_aspect_ratio = "16:9";
		else if(aspect >= 1.6)
			m_aspect_ratio = "16:10";
		else if(aspect >= 1.32)
			m_aspect_ratio = "4:3";
		else if(aspect >= 1.24)
			m_aspect_ratio = "5:4";
		else
			m_aspect_ratio = "4:3";

		//m_aspect_ratio = info_aspect_ratio.c_str();

		strDuration.Format("%02d:%02d:%02d(%d second)", hour, minute, sec, total_sec);
		SetDlgItemText(IDC_STATIC_DURATION, strDuration);
		
		mi.Close(); 
		m_segment = 1;
	} 
}

void CMconvertDlg::OnButtonAddClip() 
{
	// TODO: Add your control notification handler code here
	if(0 == m_width)
		OnButtonGetInfo();

	const char *ffmpeg_cmd = "ffmpeg -ss %s -i \"%s\" -t %s %s -vb 384k -bf 0 -r 20 "
		"-filter:v \"scale=iw*min(%d/iw\\,%d/ih):ih*min(%d/iw\\,%d/ih), "
		"pad=%d:%d:"
		"(%d-iw*min(%d/iw\\,%d/ih))/2:"
		"(%d-ih*min(%d/iw\\,%d/ih))/2\" "
		"-vcodec libxvid -ar 44100 -ab 128k -acodec mp3 \"%s\" \n\n";
	char buf[4096]		= {0};
	CString strStart, strDuration;
	CString strSegment;
	CString strFFbin;

	char *force_16_9 = "";
	if(m_cbForceWideScreen.GetCheck())
		force_16_9 = "-aspect 16:9";
	
	GetDlgItemText(IDC_EDIT_FILENAME, m_in_filename);
	GetDlgItemText(IDC_EDIT_OUT_FILENAME, m_out_prefix);
	GetDlgItemText(IDC_EDIT_TIME_FROM, strStart);
	GetDlgItemText(IDC_EDIT_TIME_DURATION, strDuration);
	GetDlgItemText(IDC_EDIT_SEGMENT, strSegment);
	GetDlgItemText(IDC_EDIT_FFMPEG_BIN, strFFbin);

	std::string final_output_filename, output_filename;
	std::string::size_type pos;
	//std::string tmp = m_in_filename.GetBuffer(0);
	//tmp.rfind('\\');
	std::string fullpath = m_in_filename.GetBuffer(0);
	pos = fullpath.rfind('\\');
	std::string fullname = fullpath.substr(pos+1, std::string::npos);
	pos = fullname.rfind('.');
	std::string filename = fullname.substr(0, pos);
	
	GetDlgItemText(IDC_EDIT_SEGMENT, strSegment);
	output_filename = std::string("[mz]") + filename 
		+ std::string("_") + std::string(strSegment)
		+ std::string(".avi");
	final_output_filename = m_out_prefix.GetBuffer(0)
		+ std::string("\\") + output_filename;

	/*char in_filename_utf8[256] = {0};
	ANSIToUTF8((char*)m_in_filename.GetBuffer(0), in_filename_utf8);

	char out_filename_utf8[256] = {0};
	ANSIToUTF8((char*)final_output_filename.c_str(), out_filename_utf8);*/

	_snprintf(buf, 4096, ffmpeg_cmd, 
		strStart.GetBuffer(0),				// start pos
		m_in_filename.GetBuffer(0),			// input filename
		strDuration.GetBuffer(0),			// duration
		force_16_9,							// aspect ratio
		OUTPUT_W, OUTPUT_H,
		OUTPUT_W, OUTPUT_H,
		OUTPUT_W, OUTPUT_H,
		OUTPUT_W, OUTPUT_W, OUTPUT_H,
		OUTPUT_H, OUTPUT_W, OUTPUT_H,
		final_output_filename.c_str());		// output filename

	char batchfile[256] ={0};
	_snprintf(batchfile, 256, "%s\\convert1.bat", strFFbin.GetBuffer(0));
	
	if(!m_pfile) {
		//::DeleteFile(batchfile);
		m_pfile = fopen(batchfile, "w");
		if(!m_pfile) {
			AfxMessageBox("failed to open bat file", MB_OK, MB_ICONERROR);
			return;
		}
	}

	fwrite(buf, strlen(buf), 1, m_pfile);

	int nIndex;
	nIndex = m_cliplist.InsertItem(m_segment - 1, NULL);
	m_cliplist.SetItemText( nIndex, 0, output_filename.c_str() );
	m_cliplist.SetItemText( nIndex, 1, strStart.GetBuffer(0) );
	m_cliplist.SetItemText( nIndex, 2, strDuration.GetBuffer(0) );

	m_segment++;
	strSegment.Format("%02d", m_segment);
	SetDlgItemText(IDC_EDIT_SEGMENT, strSegment);

	//AfxMessageBox("convert batch added!");
}

void CMconvertDlg::OnButtonSavereg() 
{
	// TODO: Add your control notification handler code here
	char *ch= "this is";
	DWORD dwordlength = strlen("this is")+1;
	int return_value=0;
    HKEY hroot = HKEY_LOCAL_MACHINE;
	HKEY hkey;
	LONG result;
    const char *subkey = "Software\\Meizu\\Mconvert";
    //DWORD dwDisposition;

	CString strBinPath, strOutPath;
	GetDlgItemText(IDC_EDIT_FFMPEG_BIN, strBinPath);
	GetDlgItemText(IDC_EDIT_OUT_FILENAME, strOutPath);

	//long result=RegCreateKeyEx(hroot, subkey, 0, NULL, 
	//	REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition);
	result = ::RegOpenKeyEx(hroot, subkey, 0, KEY_WRITE, &hkey);
	if (result != ERROR_SUCCESS) {
		AfxMessageBox("failed to read reg", MB_OK, MB_ICONERROR);
		return;
	}

	result = RegSetValueEx(hkey, 
		"BinPath", 0, REG_SZ, 
		(CONST BYTE *)strBinPath.GetBuffer(0), 
		(DWORD)(strBinPath.GetLength() + 1));
	if ( result!=ERROR_SUCCESS ){
		AfxMessageBox("failed to save bin path", MB_OK, MB_ICONERROR);
		RegCloseKey(hkey);
		return;
	}

	result = RegSetValueEx(hkey, 
		"OutPath", 0, REG_SZ, 
		(CONST BYTE *)strOutPath.GetBuffer(0), 
		(DWORD)(strOutPath.GetLength() + 1));
	if ( result!=ERROR_SUCCESS ){
		AfxMessageBox("failed to save out path", MB_OK, MB_ICONERROR);
		RegCloseKey(hkey);
		return;
	}
	
	MessageBox("reg saved");
}

int ANSIToUTF8(char* pszCode, char* UTF8code)
{
    WCHAR Unicode[100]={0,}; 
    char utf8[100]={0,};
    
    // read char Lenth
    int nUnicodeSize = MultiByteToWideChar(CP_ACP, 0, pszCode, strlen(pszCode), Unicode, sizeof(Unicode)); 
    memset(UTF8code, 0, nUnicodeSize+1);
    // read UTF-8 Lenth
    int nUTF8codeSize = WideCharToMultiByte(CP_UTF8, 0, Unicode, nUnicodeSize, UTF8code, sizeof(Unicode), NULL, NULL); 
	
    // convert to UTF-8 
    MultiByteToWideChar(CP_UTF8, 0, utf8, nUTF8codeSize, Unicode, sizeof(Unicode)); 
    UTF8code[nUTF8codeSize+1] = '\0';
    return nUTF8codeSize;
}

void CMconvertDlg::OnButtonRun() 
{
	// TODO: Add your control notification handler code here
	
	if(!m_pfile) {
		AfxMessageBox("batch is empty!", MB_OK, MB_ICONERROR);
		return;
	}

	const char *eof = "\n@pause";
	fwrite(eof, strlen(eof), 1, m_pfile);

	fclose(m_pfile);
	m_pfile = NULL;
	
	//start cmd
	STARTUPINFO sInfo;
	PROCESS_INFORMATION pInfo;
	ZeroMemory(&sInfo,sizeof(sInfo));
	sInfo.cb=sizeof(sInfo);
	sInfo.dwFlags=STARTF_USESHOWWINDOW;
	sInfo.wShowWindow=SW_SHOWNORMAL;
	
	ZeroMemory(&pInfo,sizeof(pInfo));
	
	CString strFFbin, strCVTPath, strWorkDir;
	GetDlgItemText(IDC_EDIT_FFMPEG_BIN, strFFbin);
	strCVTPath = strFFbin + "\\convert1.bat";

	if(!::CreateProcess(_T(strCVTPath.GetBuffer(0)),NULL,
		NULL,
		NULL,
		FALSE,
		0,
		NULL,
		strFFbin.GetBuffer(0),//working directory
		&sInfo,
		&pInfo))
	{
		AfxMessageBox("failed to launch converter!", MB_OK, MB_ICONSTOP);
	}
}

void CMconvertDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	if(m_pfile) {
		const char *eof = "\n@pause";
		fwrite(eof, strlen(eof), 1, m_pfile);

		fclose(m_pfile);
		m_pfile = NULL;
	}

	CDialog::OnClose();
}

void CMconvertDlg::OnButtonRemove() 
{
	// TODO: Add your control notification handler code here
	char buf[4096] = {0};

	m_cliplist.DeleteAllItems();
	m_width = 0;
	m_segment = 1;
	SetDlgItemText(IDC_EDIT_SEGMENT, "01");

	if(m_pfile) {
		fclose(m_pfile);
		m_pfile = NULL;
	}
}

void CMconvertDlg::OnDropFiles(HDROP hDropInfo)    
{  
	UINT   nCount   =   ::DragQueryFile(hDropInfo,0xFFFFFFFF,NULL,0);  
	UINT   i;  
	CString   strFileName;  
	for(i=0;i<nCount;i++)  
	{  
		::DragQueryFile(hDropInfo,i,strFileName.GetBuffer(MAX_PATH),MAX_PATH);  
		strFileName.ReleaseBuffer();  
		SetDlgItemText(IDC_EDIT_FILENAME, strFileName);
	}
	// reset clip
	m_width = 0;
	m_segment = 1;
	SetDlgItemText(IDC_EDIT_SEGMENT, "01");

	OnButtonGetInfo();
	
	CDialog::OnDropFiles(hDropInfo);  
} 